import { constantRoutes } from '../constantRoutes'
import Layout from '@/layout/index.vue'
import { cloneDeep } from 'lodash-es'
import router from '../index'
import { storeToRefs } from 'pinia'
import { useRouteMenuStoreWithOut } from '@/store/routeMenu/routeMenuStore'
import { useTagCacheStoreWithOut } from '@/store/storage/tagCacheStore'
import { menuFieldInvert, dataToRouteMenu, routerTreeToFlattening, routerToTree, treeToAscending, resetRedirect, removeEmptyCatalog } from './public'
// 静态白名单路由
import remainingRouter from '../remaining'
const routeMenuStore = useRouteMenuStoreWithOut()
const tagCacheStore = useTagCacheStoreWithOut()

// 初始化时将系统固定标签加入到标签栏
const initFixedTagToAllTag = (tabRouter: any) => {
  const { tagList } = storeToRefs(tagCacheStore)
  // 获取被缓存的标签页数据
  const hasValue = tagList.value.some((item: any) => {
    return item.path === tabRouter.path
  })
  if (tabRouter.meta.isFixed || hasValue) {
    const tagRoute = {
      path: '',
      name: '',
      meta: {}
    }
    tagRoute.path = tabRouter.path
    tagRoute.name = tabRouter.name
    tagRoute.meta = tabRouter.meta
    if (hasValue) {
      tagCacheStore.updateTagMeta({ value: tagRoute })
    }
    if (!hasValue && tabRouter.meta.showTag && tabRouter.name !== 'Layout') {
      tagCacheStore.tagOperateHandle({ mode: 'push', value: tagRoute })
    }
  }
}

// 获取前端管理的静态路由(可直接实例化，不需要权限也可以访问)
export const getConstantRoutes = () => {
  const routeArr = cloneDeep(constantRoutes).filter((item: any) => {
    return !item.permit
  })
  const result = []
  if (routeArr.length > 0) {
    routeArr.forEach((item) => {
      const itemRoute = dataToRouteMenu(item, false)
      result.push(itemRoute)
    })
  }
  /**
   * 此处要把路由数据先转树结构，为每个路由添加面包屑字段，实现面包屑功能；再转一维数组是因为本系统采取的路由策略是平级实例化路由，本系统路由不采用嵌套路由
   * 错误配置： 父级目录层是后端管理，前端管理的静态路由中却设置了其某个子级菜单层，且被设置为静态路由（不需要权限也可访问）
   * 过滤配置：父级目录是前端管理，却不存在静态子级菜单层，此时不可实例化父级目录层
   */
  const treeRoutes = routerToTree(result)
  // 删除无子级菜单层路由的目录层路由，这种目录层路由此时不应该被实例化，因为获取权限路由后，可能该目录层路由还是没有子级菜单层路由
  removeEmptyCatalog(treeRoutes)
  // 重置各目录层的重定向
  resetRedirect(treeRoutes)
  // 数据排序，使默认第一个是正确的路由，方便设置默认重定向
  treeToAscending(treeRoutes)
  const realConstantRoutes = routerTreeToFlattening(treeRoutes)
  if (realConstantRoutes.length > 0) {
    realConstantRoutes.forEach((item) => {
      initFixedTagToAllTag(item)
    })
    const routeList = []
    const rootRouteList = realConstantRoutes.filter((item) => {
      return item.meta.isRoot
    })
    const layoutRouteList = realConstantRoutes.filter((item) => {
      return !item.meta.isRoot
    })
    /**
     * 此时Layout层的路由是根路由，在登录成功后，默认是跳转该路由，该路由再重定向到具体某个路由页面
     * Layout如果存在子级路由，则默认重定向到第一个子级路由
     * Layout如果不存在子级路由，则默认重定向到其它根路由的第一个路由
     * 如果不存在其它根路由，则默认重定向到404页面
     */
    routeList.push({
      path: '/',
      name: 'Layout',
      component: Layout,
      redirect: '',
      children: layoutRouteList.length > 0 ? layoutRouteList : [],
      meta: {
        sort: 1,
        showLink: true
      }
    })
    let constantRouteList = []
    if (rootRouteList.length > 0) {
      constantRouteList = routeList.concat(...rootRouteList)
    }
    if (remainingRouter.length > 0) {
      constantRouteList = routeList.concat(...remainingRouter)
    }
    return constantRouteList
  } else {
    const routeList = []
    routeList.push({
      path: '/',
      name: 'Layout',
      component: Layout,
      redirect: '',
      children: [],
      meta: {
        sort: 1,
        showLink: true
      }
    })
    return routeList.concat(...remainingRouter)
  }
}

// 获取所有前端管理的静态路由、动态路由（包括已实例化的静态路由，这时是因为需要重新指定重定向，所以需要获取全部权限路由）
export const getAsyncRoute = (permitList) => {
  const result = []
  if (constantRoutes.length > 0) {
    if (permitList && permitList.length > 0) {
      cloneDeep(constantRoutes).forEach((item) => {
        if (!item.permit) {
          result.push(item)
        } else {
          const index = permitList.findIndex((v) => v === item.permit)
          if (index >= 0) {
            result.push(item)
          }
        }
      })
    } else {
      cloneDeep(constantRoutes).forEach((item) => {
        if (!item.permit) {
          result.push(item)
        }
      })
    }
  }
  return result
}

// 后端接口获取到的数据转化为路由
export const asyncPermitRoutes = (routeList, permitList) => {
  const result = getAsyncRoute(permitList)
  const arr = []
  if (routeList && routeList.length > 0) {
    let routerArr = []
    if (result.length > 0) {
      routerArr = cloneDeep(menuFieldInvert(routeList)).concat(...result)
    } else {
      routerArr = cloneDeep(menuFieldInvert(routeList))
    }
    routerArr.forEach((item) => {
      const itemRoute = dataToRouteMenu(item, false)
      arr.push(itemRoute)
    })
  } else {
    if (result.length > 0) {
      result.forEach((item) => {
        const itemRoute = dataToRouteMenu(item, false)
        arr.push(itemRoute)
      })
    }
  }
  if (arr.length > 0) {
    const treeRoutes = routerToTree(arr)
    // 删除无子级菜单层路由的目录层路由，这种目录层路由此时不应该被实例化，因为获取权限路由后，可能该目录层路由还是没有子级菜单层路由
    removeEmptyCatalog(treeRoutes)
    // 重置各目录层的重定向
    resetRedirect(treeRoutes)
    // 数据排序，使默认第一个是正确的路由，方便设置默认重定向
    treeToAscending(treeRoutes)
    const asyncPermitRouteList = routerTreeToFlattening(treeRoutes)
    if (asyncPermitRouteList.length > 0) {
      asyncPermitRouteList.forEach((item) => {
        initFixedTagToAllTag(item)
      })
    }
    /**
     * 过滤掉不是路由页面的数据
     * 1. 外链类型的数据
     * 2. 无实际路由页面，只是一个弹窗页面，但为了按钮权限，增加了对应的路由数据
     * 以上两种类型的数据共同点是path、name都是空
     */
    const asyncRouteList = asyncPermitRouteList.filter((item) => {
      return item.name && item.path
    })
    return asyncRouteList
  } else {
    return []
  }
}

// 获取当前路由的根级路由
export const getCurrentRootRoute = (route) => {
  let rootPath = ''
  // 根据面包屑导航找到当前路由的根路由
  if (route.meta.breadcrumb && (route.meta.breadcrumb as any).length > 0) {
    rootPath = route.meta.breadcrumb[0].path
  } else {
    rootPath = route.path
  }
  return rootPath
}

// 获取当前路由的根级路由的子级路由
export const getCurrentRootRouteChildren = (menuData, route) => {
  const rootPath = getCurrentRootRoute(route)
  let currentMenuList = []
  const recursionMenuData = (menuData) => {
    for (let i = 0; i < menuData.length; i++) {
      if (menuData[i].path === rootPath) {
        if (menuData[i].children && menuData[i].children.length > 0) {
          currentMenuList = menuData[i].children
        } else {
          // 如果当前路由没有子级数据，将自己返回显示在侧边栏
          currentMenuList = [menuData[i]]
        }
        // 使用for循环，提升代码性能，找到即终止循环
        break
      } else {
        if (menuData[i].children && menuData[i].children.length > 0) {
          recursionMenuData(menuData[i].children)
        }
      }
    }
  }
  recursionMenuData(menuData)
  return currentMenuList
}

// 获取当前路由的父级级路由的子级路由
export const getCurrentRouteParentChildren = (menuData, route) => {
  let currentMenuList = []
  const recursionMenuData = (menuData) => {
    for (let i = 0; i < menuData.length; i++) {
      if (menuData[i].meta.id === route.meta.pid) {
        if (menuData[i].children && menuData[i].children.length > 0) {
          currentMenuList = menuData[i].children
        }
        break
      } else {
        if (menuData[i].children && menuData[i].children.length > 0) {
          recursionMenuData(menuData[i].children)
        }
      }
    }
  }
  recursionMenuData(menuData)
  return currentMenuList
}

// 判断当前根路由是否有子级
export const hasChildrenRoute = (menuData, route) => {
  const rootPath = getCurrentRootRoute(route)
  let hasChildren = false
  for (let i = 0; i < menuData.length; i++) {
    if (menuData[i].path === rootPath) {
      if (menuData[i].children && menuData[i].children.length > 0) {
        hasChildren = true
      } else {
        hasChildren = false
      }
    }
  }
  return hasChildren
}

// 退出登录后重置路由
export const resetRouter = () => {
  const { routeMenuList } = storeToRefs(routeMenuStore)
  routeMenuList.value = []
  const constantRouteList = getConstantRoutes()
  const nameArr = []
  constantRouteList.forEach((item) => {
    nameArr.push(item.name)
    if (item.name === 'Layout' && item.children && item.children.length > 0) {
      item.children.forEach((v) => {
        nameArr.push(v.name)
      })
    }
  })
  router.getRoutes().forEach((route) => {
    const { name } = route
    if (name && !nameArr.includes(name)) {
      router.hasRoute(name) && router.removeRoute(name)
    }
  })
  router.options.routes = constantRouteList
}
